﻿using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

namespace Nirvana
{
    /// <summary>
    /// AssetBundle 缓存资源加载：从网络下载到的pers目录或streaming目录下读取
    /// </summary>
    public sealed class AssetBundleCache
    {
        private static Logger logger = LogSystem.GetLogger("AssetBundleCache");
        private string assetCachePath;
        private HashSet<string> abList = new HashSet<string>();

        public AssetBundleCache()
        {
            //获取出包时保存在，streaming目录下的所有资源ab名
            string txt = StreamingAssetsUtil.ReadAllText("file_list.txt");
            string[] array = txt.Split('\n');
            foreach (var p in array) abList.Add(p);
        }
    
        public string GetAssetCachePath()
        {
            if (string.IsNullOrEmpty(assetCachePath))
            {
                assetCachePath = Path.Combine(Application.persistentDataPath, "AssetCache");
                if (!Directory.Exists(assetCachePath))
                {
                    Directory.CreateDirectory(assetCachePath);
                }  
            }
            return assetCachePath;
        }
        public string GetVersion()
        {
            string path = this.GetCachePath("version.txt");
            if (File.Exists(path))
            {
                return File.ReadAllText(path);
            }
            return StreamingAssetsUtil.ReadAllText("AssetBundle/version.txt");
        }

        public void SetVersion(string A_1)
        {
            string path = Path.Combine(this.GetAssetCachePath(), "version.txt");
            File.WriteAllText(path, A_1);
        }

        /// <summary>
        /// 检测本地是否存在此ab
        /// </summary>
        public bool IsValidateCache(string assetbundle,Hash128 hash)
        {
            return !string.IsNullOrEmpty(this.GetPath(assetbundle, hash));
        }

        public void DeleteAllCache()
        {
            if (Directory.Exists(this.GetAssetCachePath()))
            {
                Directory.Delete(this.GetAssetCachePath(), true);
            }
        }

        public void Delete(string assetbundle)
        {
            string path = GetCachePath(assetbundle);
            if (File.Exists(path)) File.Delete(path);
        }

        public void Delete(string assetbundle,Hash128 hash)
        {
            string path = GetCachePath(assetbundle, hash);
            if (File.Exists(path)) File.Delete(path);
        }

        public AssetBundle LoadFromFile(string assetbundle)
        {
            string path = this.GetPath(assetbundle);
            if (string.IsNullOrEmpty(path))
            {
                return null;
            }
            return AssetBundle.LoadFromFile(path);
        }

        public AssetBundle LoadFromFile(string assetbundle,Hash128 hash,bool ingoreHash)
        {
            string path;
            if (ingoreHash)
            {
                path = this.GetPathIngoreHash(assetbundle, hash);
            }
            else
            {
                path = this.GetPath(assetbundle, hash);
            }
            if (string.IsNullOrEmpty(path)) return null;
            return AssetBundle.LoadFromFile(path);
        }


        public string GetCachePath(string bundlename)
        {
            return Path.Combine(this.GetAssetCachePath(), bundlename);
        }

        public string GetCachePath(string bundlename,Hash128 hash)
        {
            string str = Path.Combine(this.GetAssetCachePath(), bundlename);
            return str + "-" + hash.ToString();
        }

        private string GetPath(string assetbundle,Hash128 hash)
        {
            string path = this.GetCachePath(assetbundle, hash);
            if (File.Exists(path)) return path;
            path = assetbundle + "-" + hash.ToString();
            path = Path.Combine("AssetBundle", path);
            if (IsExistInStreamingAsset(path))
            {
                path = AssetManager.GetAliasResPath(path);
                return Path.Combine(Application.streamingAssetsPath, path);
            }
            return string.Empty;
        }
        private string GetPath(string assetbundle)
        {
            string path = this.GetCachePath(assetbundle);
            if (File.Exists(path)) return path;
            path = Path.Combine("AssetBundle", path);
            if (IsExistInStreamingAsset(path))
            {
                path = AssetManager.GetAliasResPath(path);
                return Path.Combine(Application.streamingAssetsPath, path);
            }
            return string.Empty;
        }

        private string GetPathIngoreHash(string assetbundle,Hash128 hash)
        {
            string path = this.GetPath(assetbundle, hash);
            if (!string.IsNullOrEmpty(path)) return path;

            path = this.GetPath(assetbundle);
            string filename = Path.GetFileName(assetbundle);
            string dirname = Path.GetDirectoryName(path);
            if (Directory.Exists(dirname))
            {
                string[] files = Directory.GetFiles(dirname, string.Format("{0}-*", filename), SearchOption.TopDirectoryOnly);
                if (files.Length > 0) return files[0];
            }

            path = Path.Combine("AssetBundle", assetbundle + "-");
            path = this.GetStreamingPath(path);
            if (string.IsNullOrEmpty(path)) return string.Empty;
            path = AssetManager.GetAliasResPath(path);
            return Path.Combine(Application.streamingAssetsPath, path);
        }
        /// <summary>
        /// streaming目录下是否存在
        /// </summary>
        public bool IsExistInStreamingAsset(string path)
        {
            path = path.Replace("\\", "/");
            return this.abList.Contains(path);
        }

        private string GetStreamingPath(string path)
        {
            path = path.Replace("\\", "/");
            foreach(string s in this.abList)
            {
                if (s.StartsWith(path)) return s;
            }
            return string.Empty;
        }

        public AssetBundleCreateRequest LoadFromFileAsync(string assetbundle)
        {
            string path = this.GetPath(assetbundle);
            if (string.IsNullOrEmpty(path)) return null;
            if (LogSystem.IsLogAct(LogActType.LoadAssetBundleFromCache))
            {
                logger.LogInfo(string.Format("LoadFromCache {0}", assetbundle));
            }
            return AssetBundle.LoadFromFileAsync(path);
        }

        public AssetBundleCreateRequest LoadFromFileAsync(string assetbundle,Hash128 hash,bool ingorehash)
        {
            string path;
            if (ingorehash)
            {
                path = this.GetPathIngoreHash(assetbundle, hash);
            }
            else
            {
                path = this.GetPath(assetbundle, hash);
            }
            if (string.IsNullOrEmpty(path)) return null;
            if (LogSystem.IsLogAct(LogActType.LoadAssetBundleFromCache))
            {
                logger.LogInfo(string.Format("LoadFromCache {0}", assetbundle));
            }
            return AssetBundle.LoadFromFileAsync(path);
        }

    }
}

